using System;
using System.Collections.Generic;
using System.Text;
using da = Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.DataAccess;
using dao = Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common;
using Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common.DataSets;


namespace Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Business
{
    /// <summary>
    /// Provides Business Logic for Service Provider operations, including CRUD.
    /// </summary>
    public class ServiceProviderManager
    {

        #region Constructor

        /// <summary>
        /// Default constructor
        /// </summary>
        public ServiceProviderManager() { }

        #endregion

        #region Get/search methods

        /// <summary>
        /// Gets a list of services providers that a specific service provider is allowed to contact
        /// </summary>
        /// <param name="serviceproviderid">The id of the service provider</param>
        /// <returns>A list of service providers that the specific service provider is allowed to contact</returns>
        public static dao.ServiceProviderList GetAllowedServiceProviders(string serviceproviderid)
        {
            dao.ServiceProviderList allowedServiceProviders = new dao.ServiceProviderList();
            dsProviderList ds = DataAccess.ServiceProvider.GetAllowedServiceProviders(serviceproviderid);
            dao.Pool currentPool = null;
            foreach (dsProviderList.ProviderListRow dr in ds.ProviderList)
            {
                if (currentPool == null || currentPool.PoolName != dr.PoolName)
                {
                    if (currentPool != null)
                        allowedServiceProviders.PoolList.Add(currentPool);
                    currentPool = new dao.Pool();
                    currentPool.PoolID = dr.PoolId;
                    currentPool.PoolName = dr.PoolName;

                }
                dao.ServiceProvider currentProvider = new dao.ServiceProvider();
                currentProvider.ServiceProviderID = dr.ServiceProviderId;
                currentProvider.ServiceProviderType = new dao.ServiceProviderType(dr.ServiceProviderTypeID, dr.ServiceProviderTypeDescription, dr.ServiceProviderTypeCode);
                currentProvider.DisplayName = dr.ServiceProviderDescription;
                currentProvider.SystemName = dr.Systemname;
                currentProvider.PublicKey = dr.publicKey;
                currentProvider.WebServiceURL = dr.WebServiceURL;
                currentProvider.EncryptionAlgorithm = dr.EncryptionAlgorithm;
                currentProvider.Contact = new dao.Contact(dr.contactName, dr.contactAddress1, dr.contactAddress2, dr.contactCity,
                                                                                           dr.contactProvince, dr.contactPostalCode, dr.contactCountry, dr.contactPhone,
                                                                                           dr.contactFax, dr.contactEmail);
                currentPool.ServiceProviders.Add(currentProvider);
            }
            allowedServiceProviders.PoolList.Add(currentPool);
            return allowedServiceProviders;
        }

        /// <summary>
        /// Gets a list of Interactive Session URI that a specific service provider is allowed to contact.
        /// </summary>
        /// <param name="serviceproviderid">The id of the service provider</param>
        /// <returns>A string respresenting the list of Interactive Session URIs</returns>
        public static string GetInteractiveSessionList(string serviceproviderid)
        {
            dsInteractiveSession ds = DataAccess.ServiceProvider.GetInteractiveSessionList(serviceproviderid);
            StringBuilder doc = new StringBuilder();
            foreach(dsInteractiveSession.InteractiveSessionRow dr in ds.InteractiveSession)
                doc.AppendLine(String.Format(@"<InteractiveSession><ServiceProviderID>{0}</ServiceProviderID><InteractiveSessionURI>{1}</InteractiveSessionURI></InteractiveSession>",dr.ServiceProviderID, dr.interactiveSessionURI));

            string result = String.Format(@"<InteractiveSessionList xmlns=""http://Microsoft.ConnectionEngine/Schemas/ServiceProviderRegister"">{0}</InteractiveSessionList>", doc.ToString());
            return result;
        }


        /// <summary>
        /// Gets a list of service providers based on search criteria
        /// </summary>
        /// <param name="serviceProviderSearchRequest">Service provider search criteria</param>
        /// <returns>A list of service providers that the specific service provider is allowed to contact</returns>
        public static dao.ServiceProviders ServiceProviderSearch(dao.ServiceProviderSearchRequest serviceProviderSearchRequest)
        {
            dao.ServiceProviders serviceProviders = new dao.ServiceProviders();
            dsProvider ds = da.ServiceProvider.ServiceProviderSearch(serviceProviderSearchRequest.DisplayName, serviceProviderSearchRequest.ServiceProviderType, serviceProviderSearchRequest.PoolID, serviceProviderSearchRequest.InPool);

            foreach (dsProvider.ProviderRow dr in ds.Provider)
            {
                dao.ServiceProvider currentProvider = new dao.ServiceProvider();
                currentProvider.ServiceProviderID = dr.ServiceProviderId;
                currentProvider.ServiceProviderType = new dao.ServiceProviderType(dr.ServiceProviderTypeID, dr.ServiceProviderTypeDescription, dr.ServiceProviderTypeCode);
                currentProvider.DisplayName = dr.ServiceProviderDescription;
                currentProvider.SystemName = dr.Systemname;
                currentProvider.PublicKey = dr.publicKey;
                currentProvider.WebServiceURL = dr.WebServiceURL;
                currentProvider.EncryptionAlgorithm = dr.EncryptionAlgorithm;
                currentProvider.Contact = new dao.Contact(dr.contactName, dr.contactAddress1, dr.contactAddress2, dr.contactCity,
                                                                                           dr.contactProvince, dr.contactPostalCode, dr.contactCountry, dr.contactPhone,
                                                                                           dr.contactFax, dr.contactEmail);
                serviceProviders.Items.Add(currentProvider);
            }
            return serviceProviders;
        }


        /// <summary>
        /// Gets a specific ServiceProvider by ID
        /// </summary>
        /// <param name="serviceproviderid">The id of the service provider to retrieve</param>
        /// <returns>A ServiceProvider object representing the requested service provider</returns>
        public static dao.ServiceProvider GetServiceProviderByID(string serviceproviderid)
        {
            dao.ServiceProvider currentProvider = new dao.ServiceProvider();
            dsProvider ds = da.ServiceProvider.GetServiceProviderByID(serviceproviderid);
            dsProvider.ProviderRow dr = ds.Provider[0];

            currentProvider.ServiceProviderID = dr.ServiceProviderId;
            currentProvider.ServiceProviderType = new dao.ServiceProviderType(dr.ServiceProviderTypeID, dr.ServiceProviderTypeDescription, dr.ServiceProviderTypeCode);
            currentProvider.DisplayName = dr.ServiceProviderDescription;
            currentProvider.SystemName = dr.Systemname;
            currentProvider.PublicKey = dr.publicKey;
            currentProvider.WebServiceURL = dr.WebServiceURL;
            currentProvider.EncryptionAlgorithm = dr.EncryptionAlgorithm;
            currentProvider.Contact = new dao.Contact(dr.contactName, dr.contactAddress1, dr.contactAddress2, dr.contactCity,
                                                                                       dr.contactProvince, dr.contactPostalCode, dr.contactCountry, dr.contactPhone,
                                                                                       dr.contactFax, dr.contactEmail);
            return currentProvider;
        }

        #endregion

        #region Insert/Update methods

        /// <summary>
        /// Updates a service provider
        /// </summary>
        /// <param name="serviceprovider">The service provider to be updated</param>
        /// <param name="userID">The user that has the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string UpdateServiceProvider(dao.ServiceProvider serviceprovider, string userID)
        {
            // return error if object is not already checked out to provider
            if (!da.ServiceProvider.ServiceProviderIsLockedByProvider(serviceprovider.ServiceProviderID, userID)) return "10";

            int result = da.ServiceProvider.ServiceProviderExists(serviceprovider.DisplayName);
            if (result == 0 || result == Convert.ToInt32(serviceprovider.ServiceProviderID))
            {

                // return error if can't update 
                if (!da.ServiceProvider.ServiceProviderUpdate(serviceprovider.ServiceProviderID,
                                                                serviceprovider.DisplayName,
                                                                serviceprovider.ServiceProviderType.ServiceProviderTypeID,
                                                                serviceprovider.SystemName,
                                                                serviceprovider.PublicKey.Replace("&lt", "<").Replace("&gt", ">"),
                                                                serviceprovider.WebServiceURL,
                                                                serviceprovider.Contact.Name,
                                                                serviceprovider.Contact.AddressLine1,
                                                                serviceprovider.Contact.AddressLine2,
                                                                serviceprovider.Contact.City,
                                                                serviceprovider.Contact.Province,
                                                                serviceprovider.Contact.PostalCode,
                                                                serviceprovider.Contact.Country,
                                                                serviceprovider.Contact.Phone,
                                                                serviceprovider.Contact.Fax,
                                                                serviceprovider.Contact.Email,
                                                                serviceprovider.EncryptionAlgorithm))
                {
                    return "99";    // can't update
                }
            }
            else
            {
                return "99"; 
            }


            // otherwise, return successful
            return "0";
        }


        /// <summary>
        /// Inserts a service provider
        /// </summary>
        /// <param name="serviceproviderid">The service provider to be deleted</param>
        /// <param name="userID">The user that has the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string InsertServiceProvider(dao.ServiceProvider serviceprovider, string userID)
        {
            string newProviderID = string.Empty;

            if (da.ServiceProvider.ServiceProviderExists(serviceprovider.DisplayName) == 0)
            {

                newProviderID = da.ServiceProvider.ServiceProviderInsert(serviceprovider.DisplayName,
                                                                        serviceprovider.ServiceProviderType.ServiceProviderTypeID,
                                                                        serviceprovider.SystemName,
                                                                        serviceprovider.PublicKey.Replace("&lt", "<").Replace("&gt", ">"),
                                                                        serviceprovider.WebServiceURL,
                                                                        serviceprovider.Contact.Name,
                                                                        serviceprovider.Contact.AddressLine1,
                                                                        serviceprovider.Contact.AddressLine2,
                                                                        serviceprovider.Contact.City,
                                                                        serviceprovider.Contact.Province,
                                                                        serviceprovider.Contact.PostalCode,
                                                                        serviceprovider.Contact.Country,
                                                                        serviceprovider.Contact.Phone,
                                                                        serviceprovider.Contact.Fax,
                                                                        serviceprovider.Contact.Email,
                                                                        serviceprovider.EncryptionAlgorithm);

            }
            // return error if insert failed (i.e didn't return a new key
            //Work Item ID: 1599
            //Modified By: SachinJo
            //if (newProviderID == "") return "99";      
            if (string.IsNullOrEmpty(newProviderID)) return "99";

            // set id to value returned from insert 
            serviceprovider.ServiceProviderID = newProviderID;
           

            // otherwise, return successful
            return "0";
        }


        #endregion

        #region Delete methods

        /// <summary>
        /// Deletes a service provider
        /// </summary>
        /// <param name="serviceproviderid">The service provider to be deleted</param>
        /// <param name="userID">The user that has the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string DeleteServiceProvider(string serviceproviderid, string userID)
        {
            // return error if object is not already checked out to provider
            if (!da.ServiceProvider.ServiceProviderIsLockedByProvider(serviceproviderid, userID)) return "10";

            //delete serviceproviderpool children
            da.ServiceProvider.ServiceProviderPoolDeleteByServiceProviderID(serviceproviderid);

            // return error if can't delete 
            if (!da.ServiceProvider.ServiceProviderDelete(serviceproviderid)) return "99";    // can't delete

            // otherwise, return successful
            return "0";
        }

        #endregion

        #region Lock/Unlock methods

        /// <summary>
        /// Checks out a service provider
        /// </summary>
        /// <param name="serviceproviderid">The service provider to be checked out</param>
        /// <param name="userID">The user that has the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderLock(string serviceproviderid, string userID)
        {
            if (!da.ServiceProvider.ServiceProviderIsLockedByProvider(serviceproviderid, userID))
            {
                // return error if object is already checked out
                if (da.ServiceProvider.ServiceProviderIsLocked(serviceproviderid)) return "9";
            }

            // return error if check out fails
            if (!da.ServiceProvider.ServiceProviderLock(serviceproviderid, userID)) return "99";

            // otherwise, return successful
            return "0";
        }


        /// <summary>
        /// Checks in a service provider
        /// </summary>
        /// <param name="serviceproviderid">The service provider that is checked out</param>
        /// <param name="userID">The user that has the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderUnlock(string serviceproviderid, string userID)
        {
            // return error if object is not already checked out to provider
            if (!da.ServiceProvider.ServiceProviderIsLockedByProvider(serviceproviderid, userID)) return "10";

            // return error if check in -fails fails
            if (!da.ServiceProvider.ServiceProviderUnlock(serviceproviderid)) return "99";

            // otherwise, return successful
            return "0";
        }


        /// <summary>
        /// Checks in all ServiceProvider checked out by a specific provider
        /// </summary>
        /// <param name="userID">The specific user</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderUnlockAll(string userID)
        {
            // return error if check in  fails
            if (!da.ServiceProvider.ServiceProviderUnlockAll(userID)) return "99";

            // otherwise, return successful
            return "0";
        }

        #endregion

        #region ServiceProviderPool Methods

        /// <summary>
        /// Adds a service provider to a pool
        /// </summary>
        /// <param name="serviceproviderid">The service provider to be added</param>
        /// <param name="poolid">The pool to be added</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string AddProviderToPool(string poolid, string serviceproviderid)
        {
            // return error if object is not already checked out to provider
            //if (!da.ServiceProvider.ServiceProviderIsLockedByProvider(serviceproviderid, userID)) return "10";

            // if new row doesn't exist, attempt to insert
            if (!da.ServiceProviderPool.ServiceProviderPoolExists(poolid, serviceproviderid))
            {
                // if unable to insert, return error.
                if (!da.ServiceProviderPool.ServiceProviderPoolInsert(poolid, serviceproviderid)) return "99";
            }

            // otherwise, return successful
            return "0";
        }


        /// <summary>
        /// Removes a service provider from a pool
        /// </summary>
        /// <param name="serviceproviderid">The service provider to be removed</param>
        /// <param name="poolid">The pool to be removed</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string RemoveProviderFromPool(string poolid, string serviceproviderid)
        {
            // return error if object is not already checked out to provider
            //if (!da.ServiceProvider.ServiceProviderIsLockedByProvider(serviceproviderid, userID)) return "10";

            // return error if can't delete 
            if (!da.ServiceProviderPool.ServiceProviderPoolDelete(poolid, serviceproviderid)) return "99";    // can't delete

            // otherwise, return successful
            return "0";
        }

        
        /// <summary>
        /// Delete a list of ServiceProviderPool entries passed as a parameter.
        /// </summary>
        /// <param name="spPoolLinks">The list of ServiceProviderPool entries to be deleted.</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderPoolLinkDelete(dao.ServiceProviderPoolLinks spPoolLinks)
        {
            string result = "0";
            foreach (dao.ServiceProviderPoolLink spPoolLink in spPoolLinks.Items)
            {
                string status = RemoveProviderFromPool(spPoolLink.PoolID.ToString(), spPoolLink.ServiceProviderID.ToString());
                if (status != "0") result = status;
            }
            // otherwise, return successful
            return result;
        }

        /// <summary>
        /// Insert a list of ServiceProviderPool entries passed as a parameter.
        /// </summary>
        /// <param name="spPoolLinks">The list of ServiceProviderPool entries to be inserted.</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderPoolLinkInsert(dao.ServiceProviderPoolLinks spPoolLinks)
        {
            string result = "0";
            foreach (dao.ServiceProviderPoolLink spPoolLink in spPoolLinks.Items)
            {
                string status = AddProviderToPool(spPoolLink.PoolID.ToString(), spPoolLink.ServiceProviderID.ToString());
                if (status != "0") result = status;
            }
            // otherwise, return successful
            return result;
        }


        #endregion

    }

}
